home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <varargs.h>
-
- /*
- * dynamem(p, s, d, dn, dn ....) allocates a d dimensional array, whose
- * dimensions are stored in a list starting at d1. Each array element is
- * of size s. p is a pointer with d levels of indirection to the memory area
- */
-
- har *malloc();
-
- har *
- ynamem(va_alist)
- a_dcl
- {
- va_list ap; /* varargs list traverser */
- int max, /* size of array to be declared */
- *q; /* pointer to dimension list */
- char **r, /* pointer to begining of the array of the
- * pointers for a dimension */
- **s1, *t, *tree; /* base pointer to begining of first array */
- int i, /* loop counters */
- j;
- char **p; /* pointer to memory area with d levels of indirection */
- int s, /* individual array element size */
- d; /* number of dimensions */
- int *d1; /* dimension list */
-
- va_start(ap);
- p = va_arg(ap, char**);
- s = va_arg(ap,int);
- d = va_arg(ap,int);
- if ((d1 = (int *) malloc (sizeof(int) * d)) == NULL)
- error("malloc returned NULL");
-
- for(i=0;i<d;i++)
- d1[i] = va_arg(ap,int);
-
- r = &tree;
- q = d1; /* first dimension */
- max = 1;
- for (i = 0; i < d - 1; i++, q++) { /* for each of the dimensions
- * but the last */
- max *= (*q);
- if ((r[0] = (char *) malloc((unsigned) max * sizeof (char **))) == NULL) {
- free(d1);
- freeup(tree,i);
- return 0;
- }
- r = (char **) r[0]; /* step through to begining of next
- * dimension array */
- }
- max *= s * (*q); /* grab actual array memory */
- if ((r[0] = (char *) malloc((unsigned) max)) == NULL) {
- free(d1);
- freeup(tree,d);
- return 0;
- }
-
- /*
- * r is now set to point to the begining of each array so that we can
- * use it to scan down each array rather than having to go across and
- * then down
- */
- r = (char **) tree; /* back to the begining of list of arrays */
- q = d1; /* back to the first dimension */
- max = 1;
- for (i = 0; i < d - 2; i++, q++) { /* we deal with the last
- * array of pointers later on */
- max *= (*q); /* number of elements in this dimension */
- for (j = 1, s1 = r + 1, t = r[0]; j < max; j++) /* scans down array for
- * first and subsequent
- * elements */
-
- /*
- * modify each of the pointers so that it points to
- * the correct position (sub-array) of the next
- * dimension array. s1 is the current position in the
- * current array. t is the current position in the
- * next array. t is incremented before s is, but it
- * starts off one behind. *(q+1) is the dimension of
- * the next array.
- */
- *s1++ = (t += sizeof (char **) * *(q + 1));
- r = (char **) r[0]; /* step through to begining of next
- * dimension array */
- }
- max *= (*q); /* max is total number of elements in the
- * last pointer array */
- for (j = 1, s1 = r + 1, t = r[0]; j < max; j++) /* same as previous
- * loop, but different
- * size factor */
- *s1++ = (t += s * *(q + 1));
- va_end(ap);
- free(d1);
- return tree; /* return base pointer */
- }
-
- /*
- * freeup releases all memory that we have already declared analogous to
- * free() when using malloc()
- */
- reeup(r,d)
- har **r;
- nt d;
- {
- char **p;
- int i;
-
- for (p = r, i = 0; i < d; p = (char **) *p,i++)
- if (p != NULL)
- free(p);
- }
-